home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 44
/
Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso
/
Aminet
/
dev
/
gui
/
gtlayout.lha
/
Source
/
LTP_LevelClass.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-01-02
|
29KB
|
1,329 lines
/*
** GadTools layout toolkit
**
** Copyright © 1993-1999 by Olaf `Olsen' Barthel
** Freely distributable.
**
** :ts=4
*/
#ifndef _GTLAYOUT_GLOBAL_H
#include "gtlayout_global.h"
#endif
/*****************************************************************************/
#include <graphics/gfxmacros.h>
#include <clib/alib_protos.h> /* For Coerce/Do/DoSuperMethod */
#include <stdarg.h>
/*****************************************************************************/
#include "Assert.h"
#ifdef DO_LEVEL_KIND /* Support code */
/*****************************************************************************/
#define FAILED (0)
/*****************************************************************************/
STATIC VOID
SliderCleanup(struct SliderClassData *sd)
{
LONG i;
WaitBlit();
for(i = 0 ; i < sd->ThumbBitMap.Depth ; i++)
{
if(sd->ThumbBitMap.Planes[i] != NULL)
{
FreeRaster(sd->ThumbBitMap.Planes[i],sd->ThumbWidth * 2,sd->ThumbHeight);
sd->ThumbBitMap.Planes[i] = NULL;
}
}
}
/****************************************************************************/
#define SCALE_UP(a) ((a) * dri->dri_Resolution.Y)/dri->dri_Resolution.X
#define SCALE_DOWN(a) ((a) * dri->dri_Resolution.X)/dri->dri_Resolution.Y
/****************************************************************************/
LONG
LTP_QuerySliderSize(struct DrawInfo *dri,WORD Reference,WORD freedom,WORD useTicks)
{
LONG thumbWidth,thumbHeight,separatorSpace,pipSpace,result;
if(Reference == 0)
Reference = dri->dri_Font->tf_YSize;
thumbHeight = (Reference + 1) & ~1;
if(thumbHeight < 8)
thumbHeight = 8;
thumbWidth = (((thumbHeight * 1618) / 1000) + 1) & ~1;
if(thumbWidth < 8)
thumbWidth = 8;
thumbHeight = SCALE_DOWN(thumbHeight);
if(thumbHeight < 8)
thumbHeight = 8;
if(freedom == FREEVERT)
{
separatorSpace = 2;
pipSpace = SCALE_UP(4);
if(useTicks != TICKS_None)
{
result = separatorSpace + pipSpace + separatorSpace + thumbWidth + separatorSpace;
if(useTicks == TICKS_Both)
result += pipSpace + separatorSpace;
}
else
{
result = separatorSpace + thumbWidth + separatorSpace;
}
}
else
{
separatorSpace = 2;
pipSpace = SCALE_DOWN(4);
if(useTicks != TICKS_None)
{
result = separatorSpace + pipSpace + separatorSpace + thumbHeight + separatorSpace;
if(useTicks == TICKS_Both)
result += pipSpace + separatorSpace;
}
else
{
result = separatorSpace + thumbHeight + separatorSpace;
}
}
return(result);
}
STATIC BOOL
SliderSetup(struct SliderClassData *sd,WORD Reference,LONG Dimension)
{
struct DrawInfo *dri = sd->DrawInfo;
BOOL IsVertical = sd->IsVertical;
BOOL GotPlanes;
LONG i;
if(Reference == 0)
Reference = dri->dri_Font->tf_YSize;
sd->ThumbHeight = (Reference + 1) & ~1;
if(sd->ThumbHeight < 8)
sd->ThumbHeight = 8;
sd->ThumbWidth = (((sd->ThumbHeight * 1618) / 1000) + 1) & ~1;
if(sd->ThumbWidth < 8)
sd->ThumbWidth = 8;
sd->ThumbHeight = SCALE_DOWN(sd->ThumbHeight);
if(sd->ThumbHeight < 8)
sd->ThumbHeight = 8;
InitBitMap(&sd->ThumbBitMap,min(8,dri->dri_Depth),sd->ThumbWidth * 2,sd->ThumbHeight);
GotPlanes = TRUE;
for(i = 0 ; i < sd->ThumbBitMap.Depth ; i++)
{
sd->ThumbBitMap.Planes[i] = AllocRaster(sd->ThumbWidth * 2,sd->ThumbHeight);
if(sd->ThumbBitMap.Planes[i] == NULL)
{
GotPlanes = FALSE;
break;
}
}
if(GotPlanes)
{
struct RastPort rp;
UWORD *pens = dri->dri_Pens;
LONG width,height;
width = height = Dimension;
InitRastPort(&rp);
rp.BitMap = &sd->ThumbBitMap;
SetRast(&rp,pens[BACKGROUNDPEN]);
SetDrMd(&rp,JAM1);
SetAPen(&rp,pens[SHINEPEN]);
if(IsVertical)
{
Move(&rp,0,(sd->ThumbHeight / 2) - 2);
Draw(&rp,0,0);
Draw(&rp,sd->ThumbWidth - 2,0);
Move(&rp,0,sd->ThumbHeight - 2);
Draw(&rp,0,sd->ThumbHeight / 2);
Draw(&rp,sd->ThumbWidth - 2,sd->ThumbHeight / 2);
SetAPen(&rp,pens[SHADOWPEN]);
Move(&rp,1,(sd->ThumbHeight / 2) - 1);
Draw(&rp,sd->ThumbWidth - 1,(sd->ThumbHeight / 2) - 1);
Draw(&rp,sd->ThumbWidth - 1,1);
Move(&rp,1,sd->ThumbHeight - 1);
Draw(&rp,sd->ThumbWidth - 1,sd->ThumbHeight - 1);
Draw(&rp,sd->ThumbWidth - 1,(sd->ThumbHeight / 2) + 1);
sd->SeparatorSpace = 2;
sd->TickSpace = SCALE_UP(4);
if(sd->UseTicks != TICKS_None)
{
sd->Width = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace + sd->ThumbWidth + sd->SeparatorSpace;
sd->Height = height;
sd->TickTop = sd->SeparatorSpace;
sd->RailTop = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace + (sd->ThumbWidth / 2) - 2;
sd->ThumbTop = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace;
if(sd->UseTicks == TICKS_Both)
sd->Width += sd->TickSpace + sd->SeparatorSpace;
}
else
{
sd->Width = sd->SeparatorSpace + sd->ThumbWidth + sd->SeparatorSpace;
sd->Height = height;
sd->TickTop = sd->SeparatorSpace;
sd->RailTop = sd->SeparatorSpace + (sd->ThumbWidth / 2) - 2;
sd->ThumbTop = sd->SeparatorSpace;
}
sd->ThumbLast = sd->Height - sd->ThumbHeight;
if(sd->ThumbMax == 0)
sd->ThumbLeft = 0;
else
sd->ThumbLeft = (sd->ThumbLast * sd->ThumbPosition) / sd->ThumbMax;
ClipBlit(&rp,0,0,&rp,sd->ThumbWidth,0,sd->ThumbWidth,sd->ThumbHeight,0xC0);
SetAPen(&rp,pens[FILLPEN]);
RectFill(&rp,sd->ThumbWidth + 1,1,sd->ThumbWidth + sd->ThumbWidth - 2,(sd->ThumbHeight / 2) - 2);
RectFill(&rp,sd->ThumbWidth + 1,(sd->ThumbHeight / 2) + 1,sd->ThumbWidth + sd->ThumbWidth - 2,sd->ThumbHeight - 2);
}
else
{
Move(&rp,(sd->ThumbWidth / 2) - 2,0);
Draw(&rp,0,0);
Draw(&rp,0,sd->ThumbHeight - 2);
Move(&rp,sd->ThumbWidth - 2,0);
Draw(&rp,sd->ThumbWidth / 2,0);
Draw(&rp,sd->ThumbWidth / 2,sd->ThumbHeight - 2);
SetAPen(&rp,pens[SHADOWPEN]);
Move(&rp,(sd->ThumbWidth / 2) - 1,1);
Draw(&rp,(sd->ThumbWidth / 2) - 1,sd->ThumbHeight - 1);
Draw(&rp,1,sd->ThumbHeight - 1);
Move(&rp,sd->ThumbWidth - 1,1);
Draw(&rp,sd->ThumbWidth - 1,sd->ThumbHeight - 1);
Draw(&rp,(sd->ThumbWidth / 2) + 1,sd->ThumbHeight - 1);
sd->SeparatorSpace = 2;
sd->TickSpace = SCALE_DOWN(4);
if(sd->UseTicks != TICKS_None)
{
sd->Width = width;
sd->Height = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace + sd->ThumbHeight + sd->SeparatorSpace;
sd->TickTop = sd->SeparatorSpace;
sd->RailTop = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace + (sd->ThumbHeight / 2) - 2;
sd->ThumbTop = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace;
if(sd->UseTicks == TICKS_Both)
sd->Height += sd->TickSpace + sd->SeparatorSpace;
}
else
{
sd->Width = width;
sd->Height = sd->SeparatorSpace + sd->ThumbHeight + sd->SeparatorSpace;
sd->TickTop = sd->SeparatorSpace;
sd->RailTop = sd->SeparatorSpace + (sd->ThumbHeight / 2) - 2;
sd->ThumbTop = sd->SeparatorSpace;
}
sd->ThumbLast = sd->Width - sd->ThumbWidth;
if(sd->ThumbMax == 0)
sd->ThumbLeft = 0;
else
sd->ThumbLeft = (sd->ThumbLast * sd->ThumbPosition) / sd->ThumbMax;
ClipBlit(&rp,0,0,&rp,sd->ThumbWidth,0,sd->ThumbWidth,sd->ThumbHeight,0xC0);
SetAPen(&rp,pens[FILLPEN]);
RectFill(&rp,sd->ThumbWidth + 1,1,sd->ThumbWidth + (sd->ThumbWidth / 2) - 2,sd->ThumbHeight - 2);
RectFill(&rp,sd->ThumbWidth + (sd->ThumbWidth / 2) + 1,1,sd->ThumbWidth + sd->ThumbWidth - 2,sd->ThumbHeight - 2);
}
}
else
{
SliderCleanup(sd);
}
return(GotPlanes);
}
STATIC VOID
DrawTicks(struct RastPort *rp,LONG left,LONG top,UWORD *pens,struct SliderClassData *sd)
{
if(sd->UseTicks != TICKS_None)
{
LONG numTicks,maxTicks;
if(sd->IsVertical)
maxTicks = (sd->Height - sd->ThumbHeight + 4) / 4;
else
maxTicks = (sd->Width - sd->ThumbWidth + 4) / 4;
if(sd->NumTicks > 0)
numTicks = sd->NumTicks;
else
numTicks = sd->ThumbMax + 1;
while(numTicks > maxTicks && numTicks > 1)
numTicks = numTicks / 2;
if(numTicks > 1)
{
LONG x,y,i;
if(sd->IsVertical)
{
for(i = 0 ; i < numTicks ; i++)
{
x = left + sd->TickTop;
y = top + (i * (sd->Height - sd->ThumbHeight)) / (numTicks - 1) + (sd->ThumbHeight / 2) - 1;
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,x,y);
Draw(rp,x + sd->TickSpace - 1,y);
SetAPen(rp,pens[SHINEPEN]);
Move(rp,x,y + 1);
Draw(rp,x + sd->TickSpace - 1,y + 1);
if(sd->UseTicks == TICKS_Both)
{
x += sd->TickSpace + sd->SeparatorSpace + sd->ThumbWidth + sd->SeparatorSpace;
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,x,y);
Draw(rp,x + sd->TickSpace - 1,y);
SetAPen(rp,pens[SHINEPEN]);
Move(rp,x,y + 1);
Draw(rp,x + sd->TickSpace - 1,y + 1);
}
}
}
else
{
for(i = 0 ; i < numTicks ; i++)
{
x = left + (i * (sd->Width - sd->ThumbWidth)) / (numTicks - 1) + (sd->ThumbWidth / 2) - 1;
y = top + sd->TickTop;
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,x,y);
Draw(rp,x,y + sd->TickSpace - 1);
SetAPen(rp,pens[SHINEPEN]);
Move(rp,x + 1,y);
Draw(rp,x + 1,y + sd->TickSpace - 1);
if(sd->UseTicks == TICKS_Both)
{
y += sd->TickSpace + sd->SeparatorSpace + sd->ThumbHeight + sd->SeparatorSpace;
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,x,y);
Draw(rp,x,y + sd->TickSpace - 1);
SetAPen(rp,pens[SHINEPEN]);
Move(rp,x + 1,y);
Draw(rp,x + 1,y + sd->TickSpace - 1);
}
}
}
}
}
}
STATIC VOID
EraseHose(struct RastPort *rp,LONG left,LONG top,LONG dimension,struct SliderClassData *sd)
{
if(sd->IsVertical)
{
UWORD width = (sd->ThumbWidth - 4) / 2;
UWORD height = dimension;
RectFill(rp,left, top,
left + width - 1, top + height - 1);
RectFill(rp,left + sd->ThumbWidth - width,top,
left + sd->ThumbWidth - 1, top + height - 1);
}
else
{
UWORD width = dimension;
UWORD height = (sd->ThumbHeight - 4) / 2;
RectFill(rp,left,top,left + width - 1,top + height - 1);
RectFill(rp,left,top + sd->ThumbHeight - height,left + width - 1,top + sd->ThumbHeight - 1);
}
}
STATIC VOID
DrawRailLeft(struct RastPort *rp,LONG left,LONG top,UWORD *pens,struct SliderClassData *sd)
{
if(sd->IsVertical)
{
if(sd->ThumbLeft > 0)
{
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,left + sd->RailTop,top);
Draw(rp,left + sd->RailTop + 2,top);
SetAPen(rp,pens[BACKGROUNDPEN]);
WritePixel(rp,left + sd->RailTop + 3,top);
EraseHose(rp,left + sd->ThumbTop,top,1,sd);
if(sd->ThumbLeft > 1)
{
EraseHose(rp,left + sd->ThumbTop,top + 1,sd->ThumbLeft - 1,sd);
RectFill(rp,left + sd->RailTop + 1,top + 1,left + sd->RailTop + 2,top + sd->ThumbLeft - 1);
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,left + sd->RailTop,top + 1);
Draw(rp,left + sd->RailTop,top + sd->ThumbLeft - 1);
SetAPen(rp,pens[SHINEPEN]);
Move(rp,left + sd->RailTop + 3,top + 1);
Draw(rp,left + sd->RailTop + 3,top + sd->ThumbLeft - 1);
}
}
}
else
{
if(sd->ThumbLeft > 0)
{
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,left,top + sd->RailTop);
Draw(rp,left,top + sd->RailTop + 2);
SetAPen(rp,pens[BACKGROUNDPEN]);
WritePixel(rp,left,top + sd->RailTop + 3);
EraseHose(rp,left,top + sd->ThumbTop,1,sd);
if(sd->ThumbLeft > 1)
{
EraseHose(rp,left + 1,top + sd->ThumbTop,sd->ThumbLeft - 1,sd);
RectFill(rp,left + 1,top + sd->RailTop + 1,left + sd->ThumbLeft - 1,top + sd->RailTop + 2);
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,left + 1,top + sd->RailTop);
Draw(rp,left + sd->ThumbLeft - 1,top + sd->RailTop);
SetAPen(rp,pens[SHINEPEN]);
Move(rp,left + 1,top + sd->RailTop + 3);
Draw(rp,left + sd->ThumbLeft - 1,top + sd->RailTop + 3);
}
}
}
}
STATIC VOID
DrawRailRight(struct RastPort *rp,LONG left,LONG top,UWORD *pens,struct SliderClassData *sd)
{
if(sd->IsVertical)
{
if(sd->ThumbLeft < sd->ThumbLast)
{
SetAPen(rp,pens[SHINEPEN]);
Move(rp,left + sd->RailTop + 1,top + sd->Height - 1);
Draw(rp,left + sd->RailTop + 3,top + sd->Height - 1);
SetAPen(rp,pens[BACKGROUNDPEN]);
WritePixel(rp,left + sd->RailTop,top + sd->Height - 1);
EraseHose(rp,left + sd->ThumbTop,top + sd->Height - 1,1,sd);
if(sd->ThumbLeft < sd->ThumbLast - 1)
{
RectFill(rp,left + sd->RailTop + 1,top + sd->ThumbLeft + sd->ThumbHeight,left + sd->RailTop + 2,top + sd->Height - 2);
EraseHose(rp,left + sd->ThumbTop,top + sd->ThumbLeft + sd->ThumbHeight,sd->ThumbLast - sd->ThumbLeft - 1,sd);
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,left + sd->RailTop,top + sd->ThumbLeft + sd->ThumbHeight);
Draw(rp,left + sd->RailTop,top + sd->Height - 2);
SetAPen(rp,pens[SHINEPEN]);
Move(rp,left + sd->RailTop + 3,top + sd->ThumbLeft + sd->ThumbHeight);
Draw(rp,left + sd->RailTop + 3,top + sd->Height - 2);
}
}
}
else
{
if(sd->ThumbLeft < sd->ThumbLast)
{
SetAPen(rp,pens[SHINEPEN]);
Move(rp,left + sd->Width - 1,top + sd->RailTop + 1);
Draw(rp,left + sd->Width - 1,top + sd->RailTop + 3);
SetAPen(rp,pens[BACKGROUNDPEN]);
WritePixel(rp,left + sd->Width - 1,top + sd->RailTop);
EraseHose(rp,left + sd->Width - 1,top + sd->ThumbTop,1,sd);
if(sd->ThumbLeft < sd->ThumbLast - 1)
{
RectFill(rp,left + sd->ThumbLeft + sd->ThumbWidth,top + sd->RailTop + 1,left + sd->Width - 2,top + sd->RailTop + 2);
EraseHose(rp,left + sd->ThumbLeft + sd->ThumbWidth,top + sd->ThumbTop,sd->ThumbLast - sd->ThumbLeft - 1,sd);
SetAPen(rp,pens[SHADOWPEN]);
Move(rp,left + sd->ThumbLeft + sd->ThumbWidth,top + sd->RailTop);
Draw(rp,left + sd->Width - 2,top + sd->RailTop);
SetAPen(rp,pens[SHINEPEN]);
Move(rp,left + sd->ThumbLeft + sd->ThumbWidth,top + sd->RailTop + 3);
Draw(rp,left + sd->Width - 2,top + sd->RailTop + 3);
}
}
}
}
STATIC VOID
EraseSlider(struct RastPort *rp,LONG left,LONG top,UWORD *pens,struct SliderClassData *sd)
{
EraseRect(rp,left,top,left + sd->Width - 1,top + sd->Height - 1);
}
STATIC VOID
DrawSlider(struct RastPort *rp,LONG left,LONG top,UWORD selected,struct SliderClassData *sd)
{
LONG offset;
if(selected)
offset = sd->ThumbWidth;
else
offset = 0;
if(sd->IsVertical)
BltBitMapRastPort(&sd->ThumbBitMap,offset,0,rp,left + sd->ThumbTop,top + sd->ThumbLeft,sd->ThumbWidth,sd->ThumbHeight,0xC0);
else
BltBitMapRastPort(&sd->ThumbBitMap,offset,0,rp,left + sd->ThumbLeft,top + sd->ThumbTop,sd->ThumbWidth,sd->ThumbHeight,0xC0);
}
/****************************************************************************/
#define G(o) ((struct Gadget *)(o))
/****************************************************************************/
STATIC VOID
DoSetMethod(Object *object,struct GadgetInfo *ginfo,...)
{
va_list args;
va_start(args,ginfo);
DoMethod(object,OM_SET,(struct TagItem *)args,ginfo);
va_end(args);
}
STATIC VOID
DoUpdateMethod(Object *object,struct GadgetInfo *ginfo,...)
{
va_list args;
va_start(args,ginfo);
DoMethod(object,OM_UPDATE,(struct TagItem *)args,ginfo,OPUF_INTERIM);
va_end(args);
}
STATIC ULONG
RenderMethod(
Class * class,
Object * object,
struct gpRender * RenderInfo)
{
struct SliderClassData *sd = INST_DATA(class,object);
struct RastPort *rp = RenderInfo->gpr_RPort;
LONG left = G(object)->LeftEdge,top = G(object)->TopEdge;
UWORD *pens = sd->DrawInfo->dri_Pens;
SetDrMd(rp,JAM1);
if(RenderInfo->gpr_Redraw != GREDRAW_UPDATE)
{
EraseSlider(rp,left,top,pens,sd);
DrawTicks(rp,left,top,pens,sd);
}
DrawRailLeft(rp,left,top,pens,sd);
DrawRailRight(rp,left,top,pens,sd);
DrawSlider(rp,left,top,G(object)->Flags & GFLG_SELECTED,sd);
if(G(object)->Flags & GFLG_DISABLED)
{
STATIC const UWORD Ghosting[2] = { 0x4444,0x1111 };
SetAPen(rp,pens[SHADOWPEN]);
SetDrMd(rp,JAM1);
SetAfPt(rp,(UWORD *)Ghosting,1);
RectFill(rp,left,top,left + G(object)->Width - 1,top + G(object)->Height - 1);
SetAfPt(rp,NULL,0);
}
return(TRUE);
}
STATIC VOID
DisposeMethod(
Class * class,
Object * object)
{
struct SliderClassData *sd = INST_DATA(class,object);
SliderCleanup(sd);
}
STATIC BOOL
GetMethod(
Class * class,
Object * object,
struct opGet * GetInfo)
{
struct SliderClassData *sd = INST_DATA(class,object);
BOOL result;
switch(GetInfo->opg_AttrID)
{
case SLA_Current:
*GetInfo->opg_Storage = sd->ThumbPosition;
result = TRUE;
break;
case SLA_Position:
*GetInfo->opg_Storage = sd->ThumbLeft;
result = TRUE;
break;
case SLA_Max:
*GetInfo->opg_Storage = sd->ThumbMax;
result = TRUE;
break;
case SLA_NumTicks:
*GetInfo->opg_Storage = sd->NumTicks;
result = TRUE;
break;
default:
result = DoSuperMethodA(class,object,(Msg)GetInfo);
break;
}
return(result);
}
STATIC BOOL
SetMethod(
Class * class,
Object * object,
struct opSet * SetInfo)
{
struct SliderClassData *sd = INST_DATA(class,object);
struct TagItem *tag,*list = SetInfo->ops_AttrList;
LONG redraw = GREDRAW_UPDATE;
BOOL rawPosition = FALSE;
BOOL updatePosition = FALSE;
BOOL result = FALSE;
BOOL refresh;
BOOL disabled;
disabled = (BOOL)((G(object)->Flags & GFLG_DISABLED) != 0);
refresh = DoSuperMethodA(class,object,(Msg)SetInfo);
while((tag = NextTagItem(&list)) != NULL)
{
switch(tag->ti_Tag)
{
case GA_Disabled:
if(disabled != (BOOL)(tag->ti_Data != 0))
{
refresh = TRUE;
redraw = GREDRAW_REDRAW;
}
break;
case SLA_Current:
result = TRUE;
if(sd->ThumbPosition != tag->ti_Data)
{
refresh = TRUE;
sd->ThumbPosition = tag->ti_Data;
updatePosition = TRUE;
}
break;
case SLA_Max:
result = TRUE;
if(sd->ThumbMax != tag->ti_Data)
{
refresh = TRUE;
redraw = GREDRAW_REDRAW;
sd->ThumbMax = tag->ti_Data;
updatePosition = TRUE;
}
break;
case SLA_Position:
result = TRUE;
if(sd->ThumbLeft != tag->ti_Data)
{
refresh = TRUE;
rawPosition = TRUE;
sd->ThumbLeft = tag->ti_Data;
updatePosition = TRUE;
}
break;
case SLA_NumTicks:
result = TRUE;
if(sd->NumTicks != tag->ti_Data)
{
sd->NumTicks = tag->ti_Data;
redraw = GREDRAW_REDRAW;
}
break;
}
}
if(refresh)
{
struct RastPort *rp;
if(updatePosition)
{
if(rawPosition)
{
if(sd->ThumbLeft > sd->ThumbLast)
sd->ThumbLeft = sd->ThumbLast;
if(sd->ThumbLast == 0)
sd->ThumbPosition = 0;
else
sd->ThumbPosition = (sd->ThumbLeft * sd->ThumbMax + (sd->ThumbLast / 2)) / sd->ThumbLast;
}
else
{
if(sd->ThumbMax == 0)
sd->ThumbLeft = 0;
else
sd->ThumbLeft = (sd->ThumbLast * sd->ThumbPosition) / sd->ThumbMax;
if(sd->ThumbLeft > sd->ThumbLast)
sd->ThumbLeft = sd->ThumbLast;
}
}
rp = ObtainGIRPort(SetInfo->ops_GInfo);
if(rp != NULL)
{
DoMethod(object,GM_RENDER,SetInfo->ops_GInfo,rp,redraw);
ReleaseGIRPort(rp);
}
}
return(result);
}
STATIC Object *
NewMethod(
Class * class,
Object * object,
struct opSet * SetInfo)
{
Object *result;
result = (Object *)DoSuperMethodA(class,object,(Msg)SetInfo);
if(result != NULL)
{
struct SliderClassData *sd = INST_DATA(class,result);
BOOL failed = FALSE;
ULONG freedom = FREEHORIZ;
struct TagItem *tag,*list = SetInfo->ops_AttrList;
WORD reference = 0;
sd->UseTicks = TICKS_None;
while((tag = NextTagItem(&list)) != NULL)
{
switch(tag->ti_Tag)
{
case PGA_Freedom:
freedom = tag->ti_Data;
break;
case SLA_DrawInfo:
sd->DrawInfo = (struct DrawInfo *)tag->ti_Data;
break;
case SLA_Current:
sd->ThumbPosition = tag->ti_Data;
break;
case SLA_Max:
sd->ThumbMax = tag->ti_Data;
break;
case SLA_UseTicks:
sd->UseTicks = tag->ti_Data;
break;
case SLA_Reference:
reference = tag->ti_Data;
break;
}
}
switch(freedom)
{
case FREEVERT:
sd->IsVertical = TRUE;
break;
case FREEHORIZ:
sd->IsVertical = FALSE;
break;
default:
failed = TRUE;
break;
}
if(sd->DrawInfo == NULL)
failed = TRUE;
if(NOT failed)
{
if(freedom == FREEVERT && G(result)->Height < 10)
failed = TRUE;
if(freedom == FREEHORIZ && G(result)->Width < 10)
failed = TRUE;
}
if(NOT failed)
{
LONG dimension,position;
if(freedom == FREEVERT)
dimension = G(result)->Height;
else
dimension = G(result)->Width;
if(SliderSetup(sd,reference,dimension) == FAILED)
failed = TRUE;
else
{
ULONG dimTag,posTag;
if(freedom == FREEVERT)
{
dimTag = GA_Width;
dimension = sd->Width;
posTag = GA_Left;
position = G(result)->LeftEdge + (G(result)->Width - sd->Width) / 2;
}
else
{
dimTag = GA_Height;
dimension = sd->Height;
posTag = GA_Top;
position = G(result)->TopEdge + (G(result)->Height - sd->Height) / 2;
}
DoMethod(result,OM_SET,SetInfo->ops_AttrList,NULL);
DoSetMethod(result,NULL,
dimTag, dimension,
posTag, position,
TAG_DONE);
}
}
if(failed)
{
CoerceMethod(class,result,OM_DISPOSE);
result = NULL;
}
}
return(result);
}
STATIC VOID
HandleSlide(
Object * object,
struct SliderClassData * sd,
struct gpInput * InputInfo)
{
LONG mousePosition;
BOOL isValid;
if(sd->IsVertical)
{
mousePosition = InputInfo->gpi_Mouse.Y;
isValid = (BOOL)(mousePosition >= 0 && mousePosition < G(object)->Height &&
InputInfo->gpi_Mouse.X >= 0 && InputInfo->gpi_Mouse.X < G(object)->Width);
}
else
{
mousePosition = InputInfo->gpi_Mouse.X;
isValid = (BOOL)(mousePosition >= 0 && mousePosition < G(object)->Width &&
InputInfo->gpi_Mouse.Y >= 0 && InputInfo->gpi_Mouse.Y < G(object)->Height);
}
if(isValid)
{
LONG direction = 0,size;
if(sd->IsVertical)
size = sd->ThumbHeight;
else
size = sd->ThumbWidth;
if(mousePosition < sd->ThumbLeft)
{
if(sd->ThumbPosition > 0)
direction = -1;
}
else if (mousePosition >= sd->ThumbLeft + size)
{
if(sd->ThumbPosition + 1 <= sd->ThumbMax)
direction = 1;
}
if(direction != 0)
{
ULONG newThumbPosition = sd->ThumbPosition + direction;
LONG thumbLeft;
if(sd->ThumbMax == 0)
thumbLeft = 0;
else
thumbLeft = (sd->ThumbLast * newThumbPosition) / sd->ThumbMax;
if(thumbLeft > sd->ThumbLast)
thumbLeft = sd->ThumbLast;
if(direction < 0 && thumbLeft < mousePosition ||
direction > 0 && thumbLeft + size >= mousePosition)
{
if(direction > 0)
mousePosition -= size - 1;
DoUpdateMethod(object,InputInfo->gpi_GInfo,
SLA_Position, mousePosition,
TAG_DONE);
}
else
{
DoUpdateMethod(object,InputInfo->gpi_GInfo,
SLA_Current, newThumbPosition,
TAG_DONE);
}
}
}
}
STATIC ULONG
InputMethod(
Class * class,
Object * object,
struct gpInput * InputInfo)
{
struct SliderClassData *sd = INST_DATA(class,object);
ULONG result = GMR_MEACTIVE;
if(InputInfo->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
{
LONG position;
switch(InputInfo->gpi_IEvent->ie_Code)
{
case SELECTUP:
result = GMR_REUSE | GMR_VERIFY;
break;
case IECODE_NOBUTTON:
if(sd->DirectHit)
{
if(sd->IsVertical)
position = InputInfo->gpi_Mouse.Y + sd->ActiveOffset;
else
position = InputInfo->gpi_Mouse.X + sd->ActiveOffset;
if(position < 0)
position = 0;
else if (position > sd->ThumbLast)
position = sd->ThumbLast;
if(position != sd->ThumbLeft)
{
DoSetMethod(object,InputInfo->gpi_GInfo,
SLA_Position, position,
TAG_DONE);
}
}
break;
}
}
return(result);
}
STATIC ULONG
ActiveMethod(
Class * class,
Object * object,
struct gpInput * InputInfo)
{
struct SliderClassData *sd = INST_DATA(class,object);
ULONG result;
struct RastPort *rp;
rp = ObtainGIRPort(InputInfo->gpi_GInfo);
if(rp != NULL)
{
if(sd->DirectHit)
{
G(object)->Flags |= GFLG_SELECTED;
DoMethod(object,GM_RENDER,InputInfo->gpi_GInfo,rp,GREDRAW_UPDATE);
}
ReleaseGIRPort(rp);
if(sd->IsVertical)
sd->ActiveOffset = sd->ThumbLeft - InputInfo->gpi_Mouse.Y;
else
sd->ActiveOffset = sd->ThumbLeft - InputInfo->gpi_Mouse.X;
if(NOT sd->DirectHit)
HandleSlide(object,sd,InputInfo);
result = GMR_MEACTIVE;
}
else
{
result = GMR_NOREUSE;
}
return(result);
}
STATIC ULONG
InactiveMethod(
Class * class,
Object * object,
struct gpGoInactive * InactiveInfo)
{
struct RastPort *rp;
rp = ObtainGIRPort(InactiveInfo->gpgi_GInfo);
if(rp != NULL)
{
struct SliderClassData *sd = INST_DATA(class,object);
if(sd->DirectHit)
{
G(object)->Flags &= ~GFLG_SELECTED;
DoMethod(object,GM_RENDER,InactiveInfo->gpgi_GInfo,rp,GREDRAW_UPDATE);
}
ReleaseGIRPort(rp);
}
return(0);
}
STATIC ULONG
HitTestMethod(
Class * class,
Object * object,
struct gpHitTest * HitInfo)
{
struct SliderClassData *sd = INST_DATA(class,object);
ULONG result;
if(sd->IsVertical)
{
if(HitInfo->gpht_Mouse.Y >= sd->ThumbLeft &&
HitInfo->gpht_Mouse.Y < sd->ThumbLeft + sd->ThumbHeight &&
HitInfo->gpht_Mouse.X >= sd->ThumbTop &&
HitInfo->gpht_Mouse.X < sd->ThumbTop + sd->ThumbWidth)
{
sd->DirectHit = TRUE;
}
else
{
sd->DirectHit = FALSE;
}
result = GMR_GADGETHIT;
}
else
{
if(HitInfo->gpht_Mouse.X >= sd->ThumbLeft &&
HitInfo->gpht_Mouse.X < sd->ThumbLeft + sd->ThumbWidth &&
HitInfo->gpht_Mouse.Y >= sd->ThumbTop &&
HitInfo->gpht_Mouse.Y < sd->ThumbTop + sd->ThumbHeight)
{
sd->DirectHit = TRUE;
}
else
{
sd->DirectHit = FALSE;
}
result = GMR_GADGETHIT;
}
return(result);
}
/*****************************************************************************/
VOID
LTP_LevelGadgetDrawLabel(LayoutHandle *Handle,ObjectNode *Node,BOOL FullRefresh)
{
if(Node->Label)
{
LevelExtra *Special = &Node->Special.Level;
LONG Current = Node->Current;
if(FullRefresh)
LTP_DrawObjectLabel(Handle,Node);
if(Special->LevelFormat)
{
UBYTE Buffer[256];
struct RastPort *RPort;
LONG LabelTop,LabelLeft;
LONG LevelWidth,LevelLen;
RPort = &Handle->RPort;
switch(Special->LevelPlace)
{
case PLACETEXT_LEFT:
LabelLeft = Node->Left - INTERWIDTH;
LabelTop = Node->Top + (Node->Height - Handle->GlyphHeight) / 2;
break;
case PLACETEXT_RIGHT:
LabelLeft = Node->Left + Node->Width + INTERWIDTH + Special->MaxLevelWidth;
LabelTop = Node->Top + (Node->Height - Handle->GlyphHeight) / 2;
break;
case PLACETEXT_ABOVE:
LabelLeft = Node->Left + (Node->Width - Special->MaxLevelWidth) / 2 + Special->MaxLevelWidth;
LabelTop = Node->Top - (Handle->GlyphHeight + INTERHEIGHT);
break;
case PLACETEXT_BELOW:
LabelLeft = Node->Left + (Node->Width - Special->MaxLevelWidth) / 2 + Special->MaxLevelWidth;
LabelTop = Node->Top + Node->Height + INTERHEIGHT;
break;
default:
return; /* Note: only in case none of the alignment types matches; should never happen! */
}
LTP_SetPens(RPort,Handle->TextPen,Handle->BackgroundPen,JAM2);
if(Special->DispFunc)
Current = (*Special->DispFunc)(Node->Host,Current);
SPrintf(Buffer,Special->LevelFormat,Current);
LevelLen = strlen(Buffer);
LevelWidth = TextLength(RPort,Buffer,LevelLen);
LTP_PrintText(RPort,Buffer,LevelLen,LabelLeft - LevelWidth,LabelTop);
if(LevelWidth < Special->MaxLevelWidth)
LTP_EraseBox(RPort,LabelLeft - Special->MaxLevelWidth,LabelTop,Special->MaxLevelWidth - LevelWidth,Handle->GlyphHeight);
}
}
}
LONG
LTP_GetCurrentLevel(ObjectNode *Node)
{
LONG Current,Max;
GetAttr(SLA_Current,Node->Host,(ULONG *)&Current);
GetAttr(SLA_Max,Node->Host,(ULONG *)&Max);
if(Node->Special.Level.Freedom == FREEVERT)
Current = Max - Current;
return(Current + Node->Special.Level.Plus);
}
/*****************************************************************************/
ULONG SAVE_DS ASM
LTP_LevelClassDispatcher(REG(a0) Class *class,REG(a2) Object *object,REG(a1) Msg msg)
{
ULONG result;
switch(msg->MethodID)
{
case OM_NEW:
result = (ULONG)NewMethod(class,object,(struct opSet *)msg);
break;
case OM_UPDATE:
case OM_SET:
result = SetMethod(class,object,(struct opSet *)msg);
break;
case OM_GET:
result = GetMethod(class,object,(struct opGet *)msg);
break;
case GM_RENDER:
result = RenderMethod(class,object,(struct gpRender *)msg);
break;
case GM_HITTEST:
result = HitTestMethod(class,object,(struct gpHitTest *)msg);
break;
case GM_GOINACTIVE:
result = InactiveMethod(class,object,(struct gpGoInactive *)msg);
break;
case GM_GOACTIVE:
result = ActiveMethod(class,object,(struct gpInput *)msg);
break;
case GM_HANDLEINPUT:
result = InputMethod(class,object,(struct gpInput *)msg);
break;
case OM_DISPOSE:
DisposeMethod(class,object);
/* Falls through to... */
default:
result = DoSuperMethodA(class,object,msg);
break;
}
return(result);
}
#endif /* DO_LEVEL_KIND */